package com.example.project.projectspringcloud.controller.front.order;

import com.example.project.projectspringcloud.common.Constants;
import com.example.project.projectspringcloud.common.OperationException;
import com.example.project.projectspringcloud.controller.BaseController;
import com.example.project.projectspringcloud.entity.Page;
import com.example.project.projectspringcloud.entity.RespBody;
import com.example.project.projectspringcloud.entity.discountcoupon.DiscountCoupon;
import com.example.project.projectspringcloud.entity.order.Order;
import com.example.project.projectspringcloud.entity.order.OrderDetail;
import com.example.project.projectspringcloud.entity.order.OrderMake;
import com.example.project.projectspringcloud.entity.sys.Area;
import com.example.project.projectspringcloud.entity.sys.Dictionary;
import com.example.project.projectspringcloud.entity.user.Evaluate;
import com.example.project.projectspringcloud.entity.user.User;
import com.example.project.projectspringcloud.entity.user.UserProfile;
import com.example.project.projectspringcloud.entity.video.Video;
import com.example.project.projectspringcloud.service.discountcoupon.DiscountCouponService;
import com.example.project.projectspringcloud.service.order.AlipayService;
import com.example.project.projectspringcloud.service.order.OrderDetailService;
import com.example.project.projectspringcloud.service.order.OrderService;
import com.example.project.projectspringcloud.service.order.WeChatPayService;
import com.example.project.projectspringcloud.service.sys.SysAreaService;
import com.example.project.projectspringcloud.service.sys.SysConfigService;
import com.example.project.projectspringcloud.service.sys.SysDictionaryService;
import com.example.project.projectspringcloud.service.user.UserEvaluateService;
import com.example.project.projectspringcloud.service.user.UserProfileService;
import com.example.project.projectspringcloud.service.user.UserService;
import com.example.project.projectspringcloud.service.video.VideoService;
import com.example.project.projectspringcloud.utils.ObjectUtil;
import com.example.project.projectspringcloud.utils.StringUtil;
import com.example.project.projectspringcloud.utils.WebUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Api(tags = "用户订单控制器")
@Controller
@RequestMapping(value = "/order")
public class OrderController extends BaseController {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private UserEvaluateService userEvaluateService;

    @Autowired
    private AlipayService alipayService;

    @Autowired
    private WeChatPayService weChatPayService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private SysDictionaryService sysDictionaryService;

    @Autowired
    private SysAreaService sysAreaService;

    @Autowired
    private DiscountCouponService discountCouponService;

    @Autowired
    private VideoService videoService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserProfileService userProfileService;

    @ApiOperation(value = "准备创建订单", notes = "返回订单填写页面")
    @GetMapping(value = "/ready/{type}")
    public String ready(@PathVariable("type") Integer type,
                        @RequestParam(value = "sameStyleId", required = false) Integer sameStyleId,
                        @RequestParam(value = "photoGrapher", required = false) Integer photoGrapher,
                        @RequestParam(value = "scriptWriter", required = false) Integer scriptWriter, Model model) throws Exception {

        // 如果是同款作品, 同款作品ID不能为空
        if (type == 1 && sameStyleId == null) {
            throw new Exception();
        }

        // 如果是私人定制, 摄影师和编剧不能为空
        if (type == 2 && (photoGrapher == null || scriptWriter == null)) {
            throw new Exception();
        }

        // 创建订单类型 1. 同款 2. 私人订制
        model.addAttribute("type", type);

        // 城市信息
        Area entity = new Area();
        entity.setIsOpen(1);
        List<Area> areas = sysAreaService.list(entity, null);
        model.addAttribute("areas", areas);

        // 作品类型字典
        model.addAttribute("videoTypes", sysDictionaryService.list(new Dictionary("video-type"), null));

        // 返回优惠券列表
        DiscountCoupon discountCoupon = new DiscountCoupon();
        discountCoupon.setOwner(WebUtil.getCurrentUser().getId());
        discountCoupon.setStatus(1);
        List<DiscountCoupon> discountCoupons = discountCouponService.list(null, discountCoupon);
        model.addAttribute("discountCoupons", discountCoupons);

        switch (type) {
            // 1. the same style
            case 1:
                Video video = videoService.get(new Video(sameStyleId));
                model.addAttribute("video", video);
                model.addAttribute("photoGrapher", userService.get(new User(video.getPhotoGrapher())));
                model.addAttribute("scriptWriter", userService.get(new User(video.getScriptWriter())));
                return isMobile() ? "m/content/order/order-form" : "content/order/order-form";
            // 2. private custom
            case 2:
                model.addAttribute("currentUser", getCurrentUser());
                model.addAttribute("photoGrapher", userService.get(new User(photoGrapher)));
                model.addAttribute("scriptWriter", userService.get(new User(scriptWriter)));
                return isMobile() ? "m/content/order/order-form" : "content/order/order-form";
            default:
                return null;
        }
    }

    @ApiOperation(value = "创建订单", notes = "用户选购, 转到创建订单页面")
    @PostMapping(value = "/create")
    public String create(@ApiParam(value = "订单所需信息") @Validated OrderMake orderMake, BindingResult bindingResult,
                         RedirectAttributes redirectAttributes) {
        // 根据订单类型拼接url, 为创建订单异常时重定向url
        String url = String.format("redirect:/order/ready/%d", orderMake.getType());
        // 1. 同款 2. 私人订制
        if (orderMake.getType() == 1) {
            url += String.format("?sameStyleId=%d", orderMake.getTheSameStyleId());
        }
        if (orderMake.getType() == 2) {
            url += String.format("?photoGrapher=%d&scriptWriter=%d", orderMake.getPhotographer(), orderMake.getScriptwriter());
        }

        if (bindingResult.getErrorCount() > 0) {
            redirectAttributes.addFlashAttribute("error", super.translateI18N(bindingResult));
            return url;
        }

        // 开始创建订单, 并进行校验
        try {
            Map result = orderService.create(orderMake);
            if ((boolean) result.get("status") != true) {
                redirectAttributes.addFlashAttribute("errors", result.get("error"));
                logger.error("OrderController - create - error", result.get("error"));
                return url;
            }
            // 转到预支付页面
            return String.format("redirect:/order/pay-ready/%d", result.get("orderId"));
        } catch (OperationException e) {
            // 创建出错,返回错误信息
            redirectAttributes.addFlashAttribute("error", e.getMessage());
            return url;
        }

    }

    @ApiOperation(value = "再来一单", notes = "再来一单")
    @GetMapping(value = "/again")
    public String again(@RequestParam("orderId") Integer orderId, RedirectAttributes redirectAttributes) {
        Order order = new Order();
        order.setUserId(super.getCurrentUserId());
        order.setId(orderId);
        order = orderService.get(order);
        if (order == null) {
            redirectAttributes.addFlashAttribute("error", super.translateI18N(Constants.Message.ORDER_DOES_NOT_EXIST));
            return "redirect:/order/list/1?statusStep=1";
        }

        OrderMake orderMake = new OrderMake();
        // 订单
        orderMake.setType(order.getType());
        orderMake.setTheSameStyleId(order.getOrderDetail().getSameStyleId());
        orderMake.setPhotographer(order.getOrderDetail().getPhotographer());
        orderMake.setScriptwriter(order.getOrderDetail().getScriptwriter());
        orderMake.setVideoType(order.getOrderDetail().getVideoType());
        orderMake.setLocation(order.getOrderDetail().getShootingLocation());
        orderMake.setExecuteDates(new Date[]{order.getOrderDetail().getShootingStartDate(), order.getOrderDetail().getShootingEndDate()});
        orderMake.setRemark(order.getOrderDetail().getRemark());

        // 套餐
        orderMake.setCombo(order.getOrderDetail().getCombo());

        // 优惠券
        orderMake.setDiscountcouponId(order.getDiscount());

        // 发票
        orderMake.setReceiptType(order.getOrderReceipt().getType());
        orderMake.setReceiptHeadType(order.getOrderReceipt().getTitleType());
        orderMake.setDutyNo(order.getOrderReceipt().getDutyNo());
        orderMake.setUnitName(order.getOrderReceipt().getUnitName());
        orderMake.setReceiptContent(order.getOrderReceipt().getContent());
        orderMake.setReceiveName(order.getOrderReceipt().getReceiveName());
        orderMake.setContactPhone(order.getOrderReceipt().getContactPhone());
        orderMake.setContactEmail(order.getOrderReceipt().getContactEmail());
        orderMake.setPostAddress(order.getOrderReceipt().getPostAddress());
        orderMake.setPostStreet(order.getOrderReceipt().getPostStreet());

        // 开始创建订单, 并进行校验
        try {
            Map result = orderService.create(orderMake);
            if ((boolean) result.get("status") != true) {
                redirectAttributes.addFlashAttribute("errors", result.get("error"));
                logger.error("OrderController - again - error", result.get("error"));
                return "redirect:/order/list/1?statusStep=1";
            }
            // 转到预支付页面
            return String.format("redirect:/order/pay-ready/%d", result.get("orderId"));
        } catch (OperationException e) {
            // 创建出错,返回错误信息
            redirectAttributes.addFlashAttribute("error", e.getMessage());
            return "redirect:/order/list/1?statusStep=1";
        }
    }

    @ApiOperation(value = "准备支付页面", notes = "准备支付页面, 选择支付方式")
    @GetMapping(value = "/pay-ready/{orderId}")
    public String payReady(@ApiParam(value = "订单ID") @PathVariable("orderId") Integer orderId, Model model) {
        Order order = orderService.get(new Order(orderId));
        model.addAttribute("order", order);

        model.addAttribute("orderUser", userService.get(new User(order.getUserId())));

        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(orderId);
        orderDetail = orderDetailService.get(orderDetail);
        model.addAttribute("orderDetail", orderDetail);
        return isMobile() ? "m/content/order/order-payment" : "content/order/order-payment";
    }

    @ApiOperation(value = "支付订单", notes = "创建完成后, 支付订单")
    @PostMapping(value = "/pay")
    public String pay(@RequestParam("type") Integer payType,
                      @RequestParam("id") Integer orderId,
                      HttpServletRequest request, HttpServletResponse response, Model model,
                      RedirectAttributes redirectAttributes) throws Exception {
        // 检查订单是否存在
        Order order = new Order();
        order.setUserId(getCurrentUser().getId());
        order.setId(orderId);
        order = orderService.get(order);
        if (order == null) {
            redirectAttributes.addFlashAttribute("error", "订单不存在");
            return String.format("redirect:/pay-ready/%s", orderId);
        }

        switch (payType) {
            // 支付宝
            case 1:
                return "redirect:" + alipayService.gotoAlipay(request, response, order);

            case 2:
                model.addAttribute("wxPayUrl", weChatPayService.getWxpayUrl(order.getNo(), String.valueOf(order.getType())));
                model.addAttribute("orderNo", order.getNo());
                model.addAttribute("orderId", order.getId());
                model.addAttribute("type", order.getType());

                // 判断是否是微信内置浏览器，并且开通了第三方 微信登录
                String agent = request.getHeader("User-Agent");
                UserProfile userProfile = new UserProfile();
                userProfile.setUserId(getCurrentUser().getId());
                userProfile = userProfileService.get(userProfile);

                // 如果是手机浏览器, 使用H5支付
                if (isMobile()) {
                    return "redirect:" + weChatPayService.h5API(order, request);
                }

                if (agent.toLowerCase().contains("micromessenger") && ObjectUtil.isNotNull(userProfile)) {
                    logger.info("WeChat Pay call Client jsapi!");
                    request.setAttribute("weixinbrowser", "true");
                    // WeChat内置浏览器, 并且用户的openid不为空, 添加jspi支付
                    // 查询当前用户的openid
                    if (ObjectUtil.isNotNull(userProfile) && StringUtils.isNotEmpty(userProfile.getValueTwo())) {
                        // 微信公众号支付请求(jspi支付)
                        model.addAttribute(weChatPayService.JSAPI(request, order, userProfile, order.getTotalPrice().toString()));
                    } else {
                        logger.error("WeChat Pay: 无法获取用户的 公众号openId");
                    }
                }
                return "content/order/order-payment-wechat";
            default:
                return null;
        }
    }

    @ApiOperation(value = "获取订单信息", notes = "返回订单信息")
    @GetMapping(value = "/get/{orderId}")
    public String get(@ApiParam(value = "订单ID") @PathVariable("orderId") Integer orderId, Model model) {
        model.addAttribute("currentUser", getCurrentUser());
        // 获取订单信息
        Order order = new Order();
        order.setUserId(getCurrentUser().getId());
        order = orderService.get(new Order(orderId));
        model.addAttribute("order", order);

        // 获取用户对该订单评论
        Evaluate evaluate = new Evaluate();
        evaluate.setUserId(getCurrentUser().getId());
        evaluate.setTarget(orderId);
        List<Evaluate> evaluates = userEvaluateService.list(null, evaluate);
        model.addAttribute("hasEvaluate", evaluates.size() > 0);

        if (order.getOrderDetail().getSameStyleId() != null) {
            model.addAttribute("video", videoService.get(new Video(order.getOrderDetail().getSameStyleId())));
        }

        return isMobile() ? "m/content/order/order-detail" : "content/order/order-detail";
    }

    @ApiOperation(value = "检查订单是否已经完成", notes = "返回true, 订单支付完成")
    @PostMapping(value = "/review/{orderNo}")
    @ResponseBody
    public RespBody review(@PathVariable("orderNo") String orderNo) {
        Order entity = new Order();
        entity.setNo(orderNo);
        entity.setUserId(getCurrentUser().getId());
        entity.setStatus(Constants.OrderStatus.PAID);
        entity = orderService.get(entity);
        if (Optional.ofNullable(entity).isPresent()) {
            return RespBody.ok(true);
        } else {
            return RespBody.error(RespBody.ERROR_CODE, false);
        }
    }

    /**
     * @param status 1. paid 2. not paid 3. cancel 4. expire
     * @param page
     * @param order
     * @param model
     * @return
     */
    @ApiOperation(value = "订单列表", notes = "根据不同状态返回订单列表")
    @GetMapping(value = "/list/{status}")
    public String list(@PathVariable("status") Integer status,
                       @RequestParam(value = "statusStep", required = false) Integer statusStep,
                       @RequestParam(value = "range", required = false) Integer range,
                       Page page, Order order, Model model) {
        // 获取订单
        User currentUser = WebUtil.getCurrentUser();
        order.setUserId(currentUser.getId());
        order.setStatus(status);
        order.setStatusStep(statusStep);
        if (range != null) {
            switch (range) {
                case 1:
                    // 七天之内
                    order.setRange(7);
                    break;
                case 2:
                    // 三个月
                    order.setRange(90);
                    break;
                case 3:
                    // 半年
                    order.setRange(183);
                    break;
            }
        }
        List<Order> orders = orderService.list(page, order);
        model.addAttribute("page", new Page<Order>(orders));
        model.addAttribute("status", status);
        model.addAttribute("statusStep", statusStep);
        model.addAttribute("order", order);
        model.addAttribute("range", range);

        // 获取字典
        List<Dictionary> dictionaries = sysDictionaryService.list(new Dictionary("order-status"), null);
        model.addAttribute("dictionaries", dictionaries);

        return isMobile() ? "m/content/order/order-list" : "content/order/order-list";
    }

    /**
     * @param status 1. paid 2. not paid 3. cancel 4. expire
     * @param page
     * @param order
     * @param model
     * @return
     */
    @ApiOperation(value = "API-page订单列表", notes = "根据不同状态返回订单列表")
    @GetMapping(value = "/api/list/{status}")
    public String content(@PathVariable("status") Integer status,
                          @RequestParam(value = "statusStep", required = false) Integer statusStep,
                          @RequestParam(value = "range", required = false) Integer range,
                          Page page, Order order, Model model) {
        // 获取订单
        User currentUser = WebUtil.getCurrentUser();
        order.setUserId(currentUser.getId());
        order.setStatus(status);
        order.setStatusStep(statusStep);
        if (range != null) {
            switch (range) {
                case 1:
                    // 七天之内
                    order.setRange(7);
                    break;
                case 2:
                    // 三个月
                    order.setRange(90);
                    break;
                case 3:
                    // 半年
                    order.setRange(183);
                    break;
            }
        }
        List<Order> orders = orderService.list(page, order);
        model.addAttribute("page", new Page<Order>(orders));
        model.addAttribute("status", status);
        model.addAttribute("statusStep", statusStep);
        model.addAttribute("order", order);
        model.addAttribute("range", range);
        return isMobile() ? "/m/" : "content/order/order-list-content";
    }

    @ApiOperation(value = "删除订单", notes = "删除选定订单")
    @DeleteMapping(value = "/delete/{ids}")
    @ResponseBody
    public RespBody delete(@PathVariable("ids") String ids) {
        Order entity = new Order();
        entity.setUserId(getCurrentUser().getId());
        Integer[] idArr = StringUtil.split(ids, ",");
        for (Integer i : idArr) {
            entity.setId(i);
            Order order = orderService.get(entity);
            if (order != null) {
                orderService.delete(new Integer[]{i});
            }
        }
        return RespBody.ok(true);
    }

}
